// Original author contact info: Owen Emlen (owene_1998@yahoo.com)
// Note: other individuals may also have contributed to this code
// Project hosted on CodePlex.com as of 1/10/2009 at http://www.codeplex.com/EmlenMud
using System.ComponentModel;
using BrainTechLLC.ThreadSafeObjects;

namespace BrainTechLLC
{
    /// <summary>
    /// Stores a log of changes that have been made to properties since the last retrieval/insert/update on a DBLayer&lt;T&gt;-derived class.
    /// Note - object instances/rows must be uniquely identifiable by primary key(s) (using the PrimaryKey(true) attribute)
    /// </summary>
    public class PropertyChangeLog<T> where T : new()
    {
        public ThreadSafeLookup<object, ThreadSafeLookup<string, PropertyChangeCollection<T>>> _propertyChanges = 
            new ThreadSafeLookup<object, ThreadSafeLookup<string, PropertyChangeCollection<T>>>();

        public PropertyChangeCollection<T> RecordPropertyChange(T item, PropertyChangeNotificationArgs changeArgs)
        {
            PropertyChangeCollection<T> propChangeCollection;
            ThreadSafeLookup<string, PropertyChangeCollection<T>> propChangeMapping;

            lock (_propertyChanges)
            {
                if (!_propertyChanges.TryGetValue(item, out propChangeMapping))
                {
                    propChangeMapping = new ThreadSafeLookup<string, PropertyChangeCollection<T>>();
                    _propertyChanges.Add(item, propChangeMapping);
                }
            }

            lock (propChangeMapping)
            {
                if (!propChangeMapping.TryGetValue(changeArgs.PropertyName, out propChangeCollection))
                {
                    propChangeCollection = new PropertyChangeCollection<T>();
                    propChangeMapping.Add(changeArgs.PropertyName, propChangeCollection);
                }
            }

            propChangeCollection.RecordChange(changeArgs);
            return propChangeCollection;
        }
    }

    public class PropertyChangeNotificationArgs : PropertyChangedEventArgs
    {
        public object _newValue;
        public object _previousValue;

        public PropertyChangeNotificationArgs(string propertyName, object oldVal, object newVal)
            : base(propertyName)
        {
            _previousValue = oldVal;
            _newValue = newVal;
        }
    }
}